package com.kira.scaffoldmvc.CommonPool;

import com.alibaba.fastjson2.JSON;
import com.kira.scaffoldmvc.Disruptor.StudentEvent;
import com.kira.scaffoldmvc.Mapper.ds1.RtaLogMapper;
import com.lmax.disruptor.RingBuffer;
import com.lmax.disruptor.dsl.Disruptor;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.util.ContentCachingRequestWrapper;
import org.springframework.web.util.ContentCachingResponseWrapper;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * HTTP请求拦截器：管理请求生命周期内的上下文对象(RtaProxyContext)
 * 主要功能：
 * 1. 请求进入时从对象池获取上下文对象并初始化
 * 2. 请求处理过程中通过ThreadLocal存储上下文
 * 3. 请求结束后记录日志并归还对象到池
 *
 * 线程安全机制：
 * - 使用ThreadLocal确保每个请求线程拥有独立的上下文实例
 * - 对象池复用机制减少频繁创建/销毁对象的开销
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class RtaProxyContextInterceptor implements HandlerInterceptor {

    @Resource
    private RtaLogMapper logMapper;

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {

        // 1. 从对象池获取可复用的上下文对象
        //    若池为空则创建新对象，避免频繁new操作带来的GC压力
        RtaLog rtaLog = RtaProxyContextHolder.borrowContext();

         Map<String, String> headerMap = Collections.list(request.getHeaderNames())//请求头的详细信息信息
                .stream()
                .collect(Collectors.toMap(name -> name, request::getHeader));
        String headerJson = JSON.toJSONString(headerMap);

        // 2. 初始化上下文：设置请求基础信息
        rtaLog.setReqTime(System.currentTimeMillis())//请求时间戳
                .setReqXid(request.getHeader("traceId"))// 全局唯一请求ID(traceId)
                .setReqType(request.getMethod())// HTTP方法(GET/POST等)
                .setReqHeader(headerJson)//请求头的详细信息信息
                .setUrl(request.getRequestURI())//请求url
                .setReqTime(System.currentTimeMillis());//请求进入时间



        // 3. 放行请求继续处理链
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {

        // 确保与preHandle中设置的是同一个实例
        RtaLog rtaLog = RtaProxyContextHolder.getContext();

        // 补充响应信息：状态码、响应时间、异常详情
        rtaLog.setRespCode(response.getStatus())// HTTP响应状态码
                .setRespTime(System.currentTimeMillis())// 响应完成时间
                .setErrorDetails(ex != null ? ex.getMessage() : "")
                .setRespBody(rtaLog.getRespBody()==null?rtaLog.getRespBody():"");//放入响应体
        logMapper.insert(rtaLog);
        // 关键资源回收步骤：
        // - 从ThreadLocal中移除引用，防止内存泄漏
        // - 重置对象状态并归还到对象池供后续请求复用
        RtaProxyContextHolder.returnContext(rtaLog);
    }
}